﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using CommonTools.Extensions;

namespace CommonTools
{
    public class CommandLineHelper
    {
        public static string Quote(string value)
        {
            return string.Format("\"{0}\"", value); ;
        }

        public static string ParseCamelCase(string text)
        {
            return System.Text.RegularExpressions.Regex.Replace(text, "([A-Z])", " $1").Trim();
        }
        
        protected string _error = "";

        public string Error 
        { 
            get { return _error; } set { _error = value; } 
        }

        protected string _output = "";

        public string Output 
        { 
            get { return _output; } set { _output = value; } 
        }

        public bool RaiseExceptions { get; set; }

        public void ClearOutput()
        {
            _error = ""; _output = "";
        }

        public Encoding CurrentEncoding = Encoding.UTF8;

        public virtual void Execute(string appPath, string args)
        {
            using (Process process = new Process())
            {
                try
                {
                    process.StartInfo.FileName = appPath;
                    process.StartInfo.Arguments = args;
                    process.StartInfo.CreateNoWindow = true;
                    process.StartInfo.RedirectStandardError = true;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.StandardOutputEncoding = CurrentEncoding;
                    process.StartInfo.StandardOutputEncoding = CurrentEncoding;
                    process.StartInfo.UseShellExecute = false;
                    process.EnableRaisingEvents = false;

                    process.OutputDataReceived += (s, e) => AddToOutput(e.Data);
                    process.ErrorDataReceived += (s, e) => AddToError(e.Data);

                    process.Start();
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    process.WaitForExit();
                    
                    if (process.HasExited)
                        process.Close();
                }
                catch (Exception ex)
                {
                    AddToError(ex.Message);
                    if (RaiseExceptions) throw;
                }

                if (RaiseExceptions && !string.IsNullOrEmpty(_error))
                    throw new Exception(_error);

            }
        }

        public void AddToOutput(string info)
        {
            AddToOutput(info, ref _output);
        }
        public void AddToError(string info)
        {
            AddToOutput(info, ref _error, true);
        }

        public virtual void AddToOutput(string info, ref string output)
        {
            AddToOutput(info, ref output, false);
        }

        public virtual void AddToOutput(string info, ref string output, bool error)
        {
            if (info.NotEmpty())
            {
                info += Environment.NewLine;
                output += info;

                if (OutputChanged != null)
                    OutputChanged(info, error);
            }
        }
        
        public event OutputChangedHandler OutputChanged;
    }
    public delegate void OutputChangedHandler(string output, bool error);
}
